﻿using Common;

namespace jq9602_jq9603.Process
{
    public class PhaseAnalyzer
    {
        // 配置参数
        public double PeakMin = 110;

        public double PeakMax = 130;
        public double StableMin = 56;
        public double StableMax = 63;
        public int StableSampleCount = 5; // 连续出现5个稳定数视为稳定开始点
        public double DataIntervalMs = 2; // 数据间隔20ms
        public int FindPeakDataCount = 50;   //从满足起始点的第一个数据开始，查找峰值的数据个数
        public double StableOffset = 0.03;  //稳定判定的幅度 ±5%；
        public int DownToZeroCount = 5; //稳定之后下降到0的数据点个数

        public AnalysisResult Analyze(List<double> data)
        {
            var result = new AnalysisResult();
            int index = 0;

            while (index < data.Count)
            {
                var phase = new PhaseData
                {
                    PeakValue = -1,
                    PeakTime = -1,
                    StableValue = -1,
                    StableStartTime = -1,
                    DurationMs = -1,
                };

                result.Phases.Add(phase);
                // 1. 查找阶段起始点（第一个进入峰值区的点）
                int phaseStart = FindNextPhaseStart(data, index);
                if (phaseStart == -1) break;

                // 2. 查找峰值点
                int peakIndex = FindPeakPoint(data, phaseStart);
                if (peakIndex == -1) break;
                phase.PeakValue = data[peakIndex];
                phase.PeakTime = peakIndex * DataIntervalMs;
                // 3. 查找稳定起始点
                int stableStart = FindStableStart(data, peakIndex);
                if (stableStart == -1) break;

                // 4. 计算稳定值（稳定阶段的平均值）
                (double medianStableValue, int stableEndIndex) = CalculateStableValue(data, stableStart);
                phase.StableValue = medianStableValue;
                phase.StableStartTime = stableStart * DataIntervalMs;
                phase.DurationMs = (stableStart - phaseStart) * DataIntervalMs;
                phase.DataPoints = data.Skip(phaseStart).Take(stableStart - phaseStart + StableSampleCount).ToList();

                // 5. 记录阶段信息

                index = stableEndIndex + DownToZeroCount;
            }

            return result;
        }

        private int FindNextPhaseStart(List<double> data, int startIndex)
        {
            for (int i = startIndex; i < data.Count; i++)
            {
                if (IsInPeakRange(data[i]))
                {
                    // 检查是否是上升趋势的开始
                    if (i > 0 && data[i] > data[i - 1])
                        return i;
                }
            }
            return -1;
        }

        private int FindMaxPoint(List<double> data, int startIndex)
        {
            double maxValue = 0;
            int maxIndex = -1;

            for (int i = startIndex; i < startIndex + FindPeakDataCount; i++)
            {
                //if (!IsInPeakRange(data[i])) break;

                if (data[i] > maxValue)
                {
                    maxValue = data[i];
                    maxIndex = i;
                }
            }
            return maxIndex;
        }

        private int FindPeakPoint(List<double> data, int startIndex)
        {
            double secondLargestValue = 0;
            int secondLargestIndex = -1;

            var maxIndex = FindMaxPoint(data, startIndex);

            for (int i = startIndex; i < startIndex + FindPeakDataCount; i++)
            {
                if (i == maxIndex)
                {
                    continue;
                }
                //if (!IsInPeakRange(data[i])) break;

                if (data[i] > secondLargestValue)
                {
                    secondLargestValue = data[i];
                    secondLargestIndex = i;
                }
            }
            return secondLargestIndex;
        }

        private int FindStableStart(List<double> data, int startIndex)
        {
            for (int i = startIndex; i < data.Count; i++)
            {
                if (IsInStableRange(data[i]))
                {
                    double stdValue = data[i];

                    // 确保后续有足够多的稳定点
                    int stableCount = 0;
                    for (int j = i; j < Math.Min(i + StableSampleCount, data.Count); j++)
                    {
                        if (IsInStableRange(stdValue, StableOffset, data[j])) stableCount++;
                        else break;
                    }

                    if (stableCount >= StableSampleCount)
                        return i;
                }
            }
            return -1;
        }

        private (double, int) CalculateStableValue(List<double> data, int startIndex)
        {
            var stableValues = new List<double>();
            for (int i = startIndex; i < Math.Min(startIndex + StableSampleCount, data.Count); i++)
            {
                stableValues.Add(data[i]);
            }
            var average = Average(stableValues);
            int stableEndIndex = startIndex;
            for (int i = startIndex + StableSampleCount; i < data.Count; i++)
            {
                if (IsInStableRange(average, StableOffset, data[i]))
                {
                    stableValues.Add(data[i]);
                    stableEndIndex = i;
                }
                else
                {
                    break;
                }
            }
            average = Average(stableValues);
            return (Math.Round(average, 4), stableEndIndex);
        }

        private double Average(List<double> values)
        {
            return values.Sum() / values.Count;
        }

        private double Median(List<double> values)
        {
            if (values.Count == 0) return 0;

            var sorted = values.OrderBy(v => v).ToList();
            int midIndex = sorted.Count / 2;

            if (sorted.Count % 2 == 0)
                return (sorted[midIndex - 1] + sorted[midIndex]) / 2;
            else
                return sorted[midIndex];
        }

        private bool IsInPeakRange(double value) => value >= PeakMin && value <= PeakMax;

        private bool IsInStableRange(double value) => value >= StableMin && value <= StableMax;

        /// <summary>
        /// 判断value是否在stdValue ±offset%的波动范围内
        /// </summary>
        /// <param name="stdValue"></param>
        /// <param name="offset"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool IsInStableRange(double stdValue, double offset, double value) =>
            value >= stdValue * (1 - offset) && value <= stdValue * (1 + offset);
    }

    public class AnalysisResult
    {
        public List<PhaseData> Phases { get; } = new List<PhaseData>();

        public void PrintReport()
        {
            MyLog.Info($"=== 分析结果（共 {Phases.Count} 个阶段）===");
            for (int i = 0; i < Phases.Count; i++)
            {
                MyLog.Info($"阶段 {i + 1}:");
                MyLog.Info($"峰值: {Phases[i].PeakValue:F2}");
                MyLog.Info($"稳定值: {Phases[i].StableValue:F2}");
                MyLog.Info($"持续时间: {Phases[i].DurationMs:F2}ms");
                MyLog.Info($"数据点数: {Phases[i].DataPoints?.Count}");
            }
        }
    }

    public class PhaseData
    {
        public double PeakValue { get; set; }
        public double PeakTime { get; set; }
        public double StableValue { get; set; }
        public double StableStartTime { get; set; }
        public double DurationMs { get; set; }
        public List<double> DataPoints { get; set; } = null!;
    }
}